// file: 'sudhir_main.cpp'
// author: Sudhir
// main.cpp used for testing the API. Please do not use/edit this file.

#include <iostream>
#include "PKB\AST\AST_Builder.h"
#include "PKB\AST\AST_Query.h"
#include "PKB\AST\AST_XLab2.h"

#include "DesignExtractor.h"

#include "Parser.h"

using namespace std;

void sudhir_waitOnExit() {
	//cout << "press enter to continue..." ; cin.get();
	cout << endl << "press enter to continue..."; cin.get();
};

void parseExpr( expr *e ) {
	expr *currExpr = e;

	if( currExpr->toString() == "+" 
		|| currExpr->toString() == "-"
		|| currExpr->toString() == "*" ) {
			cout << currExpr->toString() << " ";
			parseExpr( ((composite_expr*)currExpr)->getLHS());
			parseExpr( ((composite_expr*)currExpr)->getRHS());
	}
	else {
		cout << currExpr->toString() << " ";
		//s->pop();
	}
};

void AST_testBuild (AST_Builder &ab) {
	ab.addProcedure ( 5 );

	ab.addAssign ( 1 );
	ab.beginExpr ( OP_Plus );
	ab.beginExpr( OP_Times );

	ab.beginExpr ( OP_Plus );
	ab.setLeftBranch ( NUMERIC_EXPR_TYPE_VARIABLE,  121);
	ab.setRightBranch ( NUMERIC_EXPR_TYPE_VARIABLE, 2);
	ab.endExpr ( composite_expr::ADD_TO_RHS );

	ab.setLeftBranch( NUMERIC_EXPR_TYPE_CONSTANT, 9 );
	ab.endExpr ( composite_expr::ADD_TO_LHS );
	ab.setRightBranch( NUMERIC_EXPR_TYPE_VARIABLE, 8 );
	ab.endExpr ( composite_expr::ADD_TO_LHS );
	ab.addAssign( 1 );
	ab.addNumericExpr( NUMERIC_EXPR_TYPE_VARIABLE , 3 );
	ab.addCall( 99 );

	ab.addProcedure(2);
	ab.addAssign( 9990);
	ab.addNumericExpr(NUMERIC_EXPR_TYPE_CONSTANT, 56);
};

void testLinks_reverse ( AST_Query aq) {
	aq.gotoStmtAt ( aq.numStmts() -1 );
	cout << endl << "Query API testing..." << endl;
	cout << "========================" << endl;
	cout << "link types::  F N W T E " << endl;
	cout << "========================" << endl;
	do {
		cout << ": curr: " << aq.getCurrStmtIndex() << " :: ";
		for( int i=0; i<stmtNode::numLinks; i++) {
			cout << " ";
			if( aq.getLinksId()[i] == stmtNode::INVALID_INDEX) 
				cout << "-";
			else cout << aq.getLinksId()[i];
		}
		if( aq.getCurrStmtType() == STATEMENT_Assign ) {
			cout << " :ASSIGN :: " << aq.getLHS()->toString() << " = ";
			parseExpr(aq.getRHS());
		}
		cout << endl;
	}
	while( aq.gotoPrevLine() == STATUS_Success);
};

void testLinks_forward ( AST_Query aq) {
	// start traversing from statement munber 1
	if( aq.gotoStmtAt ( 1 ) == STATUS_Success) {
		INDEX *linksId = new INDEX[stmtNode::numLinks];
		cout << endl << "Query API testing..." << endl;
		cout << "==============\t\t============" << endl;
		cout << "link types::  \t\t F P N W T E " << endl;
		cout << "==============\t\t============" << endl;
		linksId = aq.getLinksId();
		// traverse until no more lines in program
		do{
			cout << ": curr: " << aq.getCurrStmtIndex();
			cout << "\tp[" << aq.getCurrProcID() <<"] :: ";
			linksId = aq.getLinksId();
			for( int i=0; i<stmtNode::numLinks; i++) {
				cout << " ";
				if( linksId[i] == stmtNode::INVALID_INDEX) 
					cout << "-";
				else cout << linksId[i];
			}
			if( aq.getCurrStmtType() == STATEMENT_Assign ) {
				cout << " :ASSIGN :: " << aq.getLHS()->toString() << " = ";
				parseExpr(aq.getRHS());
			}
			cout << endl;
			if (linksId[stmtNode::FOLLOWS] == stmtNode::INVALID_INDEX 
			&& linksId[stmtNode::NEXT_STMT] == stmtNode::INVALID_INDEX 
			&& linksId[stmtNode::NEXT_TO_ELSE] == stmtNode::INVALID_INDEX 
			&& linksId[stmtNode::NEXT_TO_THEN] == stmtNode::INVALID_INDEX 
			&& linksId[stmtNode::NEXT_TO_WHILE] == stmtNode::INVALID_INDEX 
			&& linksId[stmtNode::PARENT] == stmtNode::INVALID_INDEX) {
				cout << "end of procedure: "<< aq.getCurrProcID() << endl;
			}
		}while( aq.gotoNextLine() == STATUS_Success );
	}
};

int main() {
	AST a;
	// building API testing..
	AST_Builder ab(&a);
	//AST_testBuild(ab);
	STRING srcFile = "testSrcFiles\\src1.txt";
	Parser p(&a);
	p.Parse(srcFile);

	// end of build AST section..
	//ab.listAllStmts();

	// Query APIs testing..
	AST_Query aq (&a);
	testLinks_forward (aq);


	sudhir_waitOnExit ();
	return 0;
}